package com.mazaiting.instructions.comparisons;

import com.mazaiting.instructions.base.NoOperandsInstruction;
import com.mazaiting.rtda.MtFrame;
import com.mazaiting.rtda.MtOperandStack;

/**
 * 用于比较double变量
 *
 * @author mazaiting
 * @since 2021/8/15
 */
public class DCmpInstruction {

    /**
     * 双精度比较
     * 由于浮点数计算有可能产生NaN（Not a Number）值，所以比较两个浮点数时，除了大于、等于、小于之外，
     * 还有第4种结果：无法比较
     * @param frame 栈帧
     * @param flag true: 压入 1; false: 压入 -1
     */
    private static void dCmp(MtFrame frame, boolean flag) {
        MtOperandStack stack = frame.getOperandStack();
        double v1 = stack.popDouble();
        double v2 = stack.popDouble();
        if (v2 > v1) {
            stack.pushInt(1);
        } else if (v1 == v2) {
            stack.pushInt(0);
        } else if (v2 < v1) {
            stack.pushInt(-1);
        } else if (flag) {
            stack.pushInt(1);
        } else {
            stack.pushInt(-1);
        }
    }

    /**
     * 由于浮点数计算有可能产生NaN（Not a Number）值，所以比较两个浮点数时，除了大于、等于、小于之外，
     * 还有第4种结果：无法比较
     */
    public static class DCmpG extends NoOperandsInstruction {
        @Override
        public void execute(MtFrame frame) {
            dCmp(frame, true);
        }
    }

    /**
     * 由于浮点数计算有可能产生NaN（Not a Number）值，所以比较两个浮点数时，除了大于、等于、小于之外，
     * 还有第4种结果：无法比较
     */
    public static class DCmpL extends NoOperandsInstruction {
        @Override
        public void execute(MtFrame frame) {
            dCmp(frame, false);
        }
    }
}
